import { DB } from "../db"
import { UserDefine } from "../../../kds-base-define/src/UserDefine"
import { Rpc } from "../rpc"
import { MutexDefine } from "../../../kds-base-define/src/MutexDefine"
import { Log } from "../log"
import { ServerValues } from "../../../kds-base-define/src/ServerConfig"
import { db } from "kdweb-core"
import { MemCaches } from "../cache/MemCaches"
import moment = require("moment")

async function getUserLogin(h:string,userIDOrSK:number | string) {
	let idx = {}
	if(typeof(userIDOrSK) == "number") {
		idx = {userID:userIDOrSK}
	} else {
		idx = {sk:userIDOrSK}
	}
	return await MemCaches.loginData.getData(idx)
	// let loginData:UserDefine.LoginData = await DB.login.getSingle(DB.t_login,idx)
	// if(loginData) {
	// 	return loginData
	// }
	// return null
}
async function getUserLoginWithPhone(h:string,phoneNumber:string) {
	return await MemCaches.loginData.getData({phoneNumber:phoneNumber})
	// let loginData:UserDefine.LoginData = await DB.login.getSingle(DB.t_login,{phoneNumber:phoneNumber})
	// if(loginData) {
	// 	return loginData
	// }
	// return null
}
async function getUserLoginWithApiID(h:string,apiID:string) {
	return await MemCaches.loginData.getData({apiID:apiID})
	// let loginData:UserDefine.LoginData = await DB.login.getSingle(DB.t_login,{apiID:apiID})
	// if(loginData) {
	// 	return loginData
	// }
	// return null
}

async function getUserDB(h: string, userID: string) {
	return await MemCaches.loginData.getUserDB({ userID: userID })
}

async function deleteById(h: string, userID: string) {
	return await MemCaches.loginData.deleteDataById({ userID: userID })
}

async function newUserLogin(h:string,loginData:UserDefine.LoginData) {
	await MemCaches.loginData.setData(loginData,{apiID:loginData.apiID})
	return true 
	// if(loginData.userID == null || loginData.sk == null) {
	// 	return false 
	// }
	// return await DB.login.insert(DB.t_login,loginData) > 0
}

async function updateUserLogin(h:string,loginData:UserDefine.LoginData) {
	await MemCaches.loginData.setData(loginData,{apiID:loginData.apiID})
	return true 
	// let ret = await DB.login.update(DB.t_login,{userID:loginData.userID},loginData) >= 0
	// return ret 
}

let dbGetAllLogin = DB.get(ServerValues.dbLogin,"db-login-get-all")
async function getAllUserIDsByAreaID(h:string,areaID:string) {
	let idx = null 
	if(areaID) {
		idx = {
			areaID:areaID
		}
	} else {
		idx = {}
	}
	let cursor = await dbGetAllLogin.getCursor(DB.t_login,idx)
	let ret = await cursor.entity.map((loginData:UserDefine.LoginData)=>loginData.userID)
	let userIDs = await ret.toArray()
	return userIDs
}

async function getAllLoginDataByAreaID(h:string,areaID:string) {
	let idx = null 
	if(areaID) {
		idx = {
			areaID:areaID
		}
	} else {
		idx = {}
	}
	return await dbGetAllLogin.get(DB.t_login,idx)
}

async function getAreaID(h:string,userID:number) {
	let loginData = await getUserLogin(h,userID)
	if(loginData) {
		return loginData.areaID
	}
	return null 
}

async function getUserInfo(h:string,userIDOrSK:number | string) {
	let idx = {}
	if(typeof(userIDOrSK) == "number") {
		idx = {userID:userIDOrSK}
	} else {
		idx = {sk:userIDOrSK}
	}
	let userInfo:UserDefine.UserInfoData = await DB.lobby.getSingle(DB.t_userInfo,idx)
	if(userInfo) {
		return userInfo
	}
	return null
}

async function newUserInfo(h:string,userInfo:UserDefine.UserInfoData) {
	if(userInfo.userID == null || userInfo.sk == null) {
		return false 
	}
	return await DB.lobby.insert(DB.t_userInfo,userInfo) > 0
}

async function updateUserInfo(h:string,userInfo:UserDefine.UserInfoData) {
	return await DB.lobby.update(DB.t_userInfo,{userID:userInfo.userID},userInfo) >= 0
}

async function createUpdateLog(h: string, params:{
	goldCount: number,
	cardCount: number,
	diamondCount: number,
	id: number,
}) {
	params['time'] = moment().format('YYYY-MM-DD HH:mm:ss')
	return await DB.get('tds-admin').insert('t_user_assets_log', params) > 0
}

async function getBonusLogAll(h: string) {
    return await DB.get('tds-admin').getOption('t_user_assets_log', {})
}

let dbGetAllLobby = DB.get(ServerValues.dbLobby,"db-userInfo-get-all")
async function getUserInfoByUserIDs(h:string,userIDs:number[]) {
	let idx = {
		userID:{
			$in:userIDs
		}
	}
	return await DB.lobby.get(DB.t_userInfo,idx)
}

async function setAward(h: string, userID: number) {
	let time = Math.floor(new Date().getTime() / 1000)
	let t_award_flag = 't_award_flag'
	await DB.redis.hdel(t_award_flag, userID.toString())
	return await DB.redis.hset(t_award_flag, userID.toString(), time) > 0
}
async function getAward(h: string, userID: number) {
	let t_award_flag = 't_award_flag'
	let date = await DB.redis.hget(t_award_flag, userID.toString())
	let time = Math.floor(new Date().getTime() / 1000)
	let status: boolean = true;
	if(!date || Number(time) - Number(date) < 10) {
		if(date) {
			await DB.redis.hdel(t_award_flag, userID.toString())
		}
		status = false
	}
	return {status:status}
}
   
async function setUserRoomID(h:string,userID:number,roomID:number) {
	await removeUserRoomID(h,userID)
	return await DB.srs.insert(DB.t_srsUserRoomID,{
		userID:userID,
		roomID:roomID
	}) > 0
}

async function getUserRoomID(h:string,userID:number) {
	let results:UserDefine.UserRoomData[] = await DB.srs.get(DB.t_srsUserRoomID,{userID:userID},1)
	if(results == null || results.length == 0) {
		return null
	}
	return results[0].roomID
}

async function removeUserRoomID(h:string,userID:number) {
	await DB.srs.del(DB.t_srsUserRoomID,{userID:userID})
	return true 
}

export let RpcUserLogin = {
    get: getUserLogin,
    getPhone: getUserLoginWithPhone,
    getApiID: getUserLoginWithApiID,
    new: newUserLogin,
    update: updateUserLogin,
    getAreaID: getAreaID,
    getAllUserIDsByAreaID: getAllUserIDsByAreaID,
    getAllLoginDataByAreaID: getAllLoginDataByAreaID,
	deleteDatasById: deleteById,
	getUserDB: getUserDB,
}
export let RpcUserInfo = {
    get: getUserInfo,
    new: newUserInfo,
    update: updateUserInfo,
    addUpdateLog: createUpdateLog,

    getUserInfoByUserIDs,
}

export let RpcNewGoldInfo = {
	setAward: setAward,
	getAward: getAward,
}

export let RpcUserRoomStatus = {
	get:getUserRoomID,
	set:setUserRoomID,
	remove:removeUserRoomID,
}

export type RealData = {
	userID: number,
	sk: string,
	uname: string,
	phone: string,
	cardid: string
}

let dbUserNode = DB.get(ServerValues.dbSrs,"srs-user-node")
let redis = DB.redis
async function setUserNodeName(h:string,userID:number,nodeName:string) {
	await removeUserNodeName(h,userID)
	return await dbUserNode.insert(DB.t_srsUserNodeData,{
		userID:userID,
		nodeName:nodeName
	}) > 0
}

async function getUserNodeName(h:string,userID:number) {
	let results:UserDefine.UserNodeData[] = await dbUserNode.get(DB.t_srsUserNodeData,{userID:userID},1)
	if(results == null || results.length == 0) {
		return null
	}
	return results[0].nodeName
}

async function removeUserNodeName(h:string,userID:number) {
	await dbUserNode.del(DB.t_srsUserNodeData,{userID:userID})
}

async function removeUserWithNodeName(h:string,nodeName:string) {
	await dbUserNode.delMany(DB.t_srsUserNodeData,{nodeName:nodeName})
}

export let RpcUserNodeStatus = {
	get:getUserNodeName,
	set:setUserNodeName,
	remove:removeUserNodeName,
	removeNode:removeUserWithNodeName,
}

let t_redisUserSrsNode = "t_user_srs_node"
async function redis_setUserNodeName(h:string,userID:number,nodeName:string) {
	await DB.redis.hset(t_redisUserSrsNode,userID.toString(),nodeName)
	await DB.redis.hset(t_redisUserFlag + "_" + nodeName,userID.toString(),true)
}

async function redis_getUserNodeName(h:string,userID:number) {
	let ret:string = await DB.redis.hget(t_redisUserSrsNode,userID.toString())
	return ret 
}

async function redis_removeUserNodeName(h:string,userID:number,nodeName?:string) {
	let curNodeName = await DB.redis.hget(t_redisUserSrsNode,userID.toString())
	if(curNodeName) {
		if(nodeName) {
			if(curNodeName != nodeName) {
				return false 
			}
		}
		DB.redis.hdel(t_redisUserFlag + "_" + curNodeName,userID.toString())	
		DB.redis.hdel(t_redisUserSrsNode,userID.toString())
	}
	return true 
}

async function redis_getUserNodeCount(h:string) {
	let count = await DB.redis.hlen(t_redisUserSrsNode)
	return count 
}

async function redis_removeUserWithNodeName(h:string,nodeName:string) {
	let objs = await DB.redis.hgetall(t_redisUserFlag + "_" + nodeName) || {}
	for(let key of Object.keys(objs)) {
		DB.redis.hdel(t_redisUserSrsNode,key)
	}
	await DB.redis.del(t_redisUserFlag + "_" + nodeName)
}

export let RpcUserNodeStatusRedis = {
	get:redis_getUserNodeName,
	set:redis_setUserNodeName,
	remove:redis_removeUserNodeName,
	removeNode:redis_removeUserWithNodeName,
	count:redis_getUserNodeCount
}

async function getUserFlag(h:string,userID:number,flagName:string) {
	let flagData:UserDefine.UserFlagData = await DB.login.getSingle(DB.t_loginUserFlag,{userID:userID})
	if(flagData == null) {
		return flagData 
	}
	return flagData.data[flagName]
}

async function setUserFlag(h:string,userID:number,flagName:string,value:any) {
	let flagData:UserDefine.UserFlagData = await DB.login.getSingle(DB.t_loginUserFlag,{userID:userID})
	let insert = false 
	if(flagData == null) {
		insert = true 
		flagData = {
			userID:userID,
			data:{},
		}
	}
	flagData.data[flagName] = value 
	if(insert) {
		return await DB.login.insert(DB.t_loginUserFlag,flagData) > 0
	}
	return await DB.login.update(DB.t_loginUserFlag,{userID:userID},flagData) >= 0
}
async function removeUserFlag(h:String,userID:number,flagName:string) {
	let flagData:UserDefine.UserFlagData = await DB.login.getSingle(DB.t_loginUserFlag,{userID:userID})
	if(flagData == null) {
		return true 
	}
	delete flagData.data[flagName]
	return await DB.login.update(DB.t_loginUserFlag,{userID:userID},flagData) >= 0
}
async function clearUserFlags(h:string,userID:number) {
	await DB.login.del(DB.t_loginUserFlag,{userID:userID})
	return true 
}

export let RpcUserFlag = {
	get:getUserFlag,
	set:setUserFlag,
	remove:removeUserFlag,
	clear:clearUserFlags,
}

export let t_redisUserFlag = "t_user_flag"
async function redis_getUserFlag(h:string,userID:number,flagName:string) {
	let mainKey = t_redisUserFlag + ":" + flagName
	let flagData:UserDefine.UserFlagData = await DB.redis.hget(mainKey,userID.toString(),true)
	if(flagData == null) {
		return flagData 
	}
	return flagData.data[flagName]
}

async function redis_setUserFlag(h:string,userID:number,flagName:string,value:any) {
	let mainKey = t_redisUserFlag + ":" + flagName
	let flagData:UserDefine.UserFlagData = await DB.redis.hget(mainKey,userID.toString(),true)
	if(flagData == null) {
		flagData = {
			userID:userID,
			data:{},
		}
	}
	flagData.data[flagName] = value 
	await DB.redis.hset(mainKey,userID.toString(),flagData,true)
	return true 
}
async function redis_removeUserFlag(h:String,userID:number,flagName:string) {
	let mainKey = t_redisUserFlag + ":" + flagName
	let flagData:UserDefine.UserFlagData = await DB.redis.hget(mainKey,userID.toString(),true)
	if(flagData == null) {
		return true 
	}
	delete flagData.data[flagName]
	await DB.redis.hset(mainKey,userID.toString(),flagData,true)
	return true 
}
async function redis_clearUserFlags(h:string,userID:number) {
	await DB.redis.hdel(t_redisUserFlag,userID.toString())
	return true 
}

export let RpcUserFlagRedis = {
	get:redis_getUserFlag,
	set:redis_setUserFlag,
	remove:redis_removeUserFlag,
	clear:redis_clearUserFlags,
}

export let RpcBonusTea = {
    getAll: getBonusLogAll,
}